<?php
namespace cms\modules\v1\models\admin;

use common\models\Functions;
use common\models\Status;
use common\services\google\GoogleAuthenticator;
use common\utils\CodeImgGenerate;
use yii\base\Exception;
use Yii;

class Admin extends \cms\modules\common\models\Admin
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%admin_info}}';
    }

    public $login_name;   #用户名
    public $verifyCode;   #验证码
    public $password;      #密码
    public $re_password;   #确认密码
    public $new_password;   #新密码
    public $re_new_password;   #确认新密码
    public $rememberMe ;  #记住我
    public $role_type ;  #角色ID
    public $code ;  #验证码

    private $_admin;

    const GET_ACCESS_TOKEN = 'generate_access_token';

    /**
     * 验证规则
     */
    public function rules()
    {
        return [
            #登录
//            [['login_name','password','code'], 'required','message' => '{attribute}不能为空','on' => 'login'],
            [['login_name','password'], 'required','message' => '{attribute}不能为空','on' => 'login'],
            // 自定义validatePassword()函数验证密码
            ['password', 'validatePassword','on' => 'login'],
//            ['code', "captcha", 'captchaAction'=>'cms/modules/v1/controllers/login/captcha','message'=>'验证码不正确', "on" => "login"],
//            ['code', "codeVerify", "on" => "login"],

            #添加
//            [['role_type','login_name','password', 're_password'], 'required', 'message' => '{attribute}不能为空', 'on' => 'addAdmin'],
//            ['login_name', 'validLoginNameUnique', 'message' => '{attribute}已存在', 'on' => 'addAdmin'],
//            ['re_password', 'compare', 'compareAttribute' => 'password', 'message' => '密码不一致', 'on' => 'addAdmin'],

            #修改密码
//            ['password','required','message' => '{attribute}不能为空','on' => 'editPwd'],
//            ['password','validEditPassword','on' => 'editPwd'],
//            [['new_password','re_new_password'],'required','message' => '{attribute}不能为空','on' => 'editPwd'],
//            ['re_new_password', 'compare', 'compareAttribute' => 'new_password', 'message' => '密码不一致', 'on' => 'editPwd'],

        ];
    }

    /**
     * 设置属性名称
     * @return array
     */
    public function attributeLabels() {
        return [
            'verifyCode' => '验证码',
            'rememberMe' => '记住我',
            'login_name' => '账号',
            'password' => '密码',
            're_password' => '确认密码',
            'new_password' => '新密码',
            're_new_password' => '确认密码',
            'role_type' => '角色',
            'code' => '验证码',
        ];
    }

    /**
     * 设置场景
     * @return array
     */
    public function scenarios() {
        $newScenarios =  [
            'login' => ['login_name','password','code'],
            'editPwd' => ['password','re_new_password','new_password','id'],
            'addAdmin' => ['login_name','password','re_password','role_type'],
        ];
        return array_merge(parent::scenarios(), $newScenarios);
    }

    /**
     * 自定义的密码认证方法  该方法作为内部验证密码方法.
     * @param string $attribute
     */
    public function validatePassword($attribute) {
        if (!$this->hasErrors()) {
            $this->_admin = $this->getAdmin();

            if (!$this->_admin || !$this->_admin->validatePassword($this->password)) {
                $this->addError($attribute, '用户名或者密码错误.');
            }
            if(!$this->validateStatus($this->login_name))  {
                $this->addError($attribute,'账号已被禁用，请联系管理员.');
            }
        }
    }

    /**
     * 验证状态
     * @param $login_name
     *
     * @return bool
     */
    public function validateStatus($login_name) {
        if (empty($imgCode)) {
            return $login_name;
        }
        $statusArray = static::getOneByWhere(['login_name' => $login_name], ['status']);
        return intval($statusArray['status']) === Status::COMMON_STATUS_SHOW;
    }


    /**
     * 图像验证码
     */
    public function codeVerify($attribute)
    {
        if (!$this->hasErrors()) {
            $check = (new CodeImgGenerate()) -> check($this->code);
            if (!$check) {
                $this->addError($attribute, '验证码错误.');
            }
        }
    }

    //============================= 登录开始 =============================
    public function login() {
        $this->on(self::GET_ACCESS_TOKEN, [$this, 'onGenerateAccessToken']);
        if ($this->validate()) {
            if ($this->updateLogin($this->_admin->id)) {
                $this->trigger(self::GET_ACCESS_TOKEN);
                return $this->_admin;
            }
        }

        return null;
    }


    /**
     * 退出操作
     * @return array
     */
    public function doLogout() {
        $token = Yii::$app->request->headers->get('access-token');
        if (!empty($token)) {
            $where['access_token'] = $token;
            $data['access_token'] = '';
            static::updateData($data, $where);
        }

        return Functions::formatRestAPI(0, '退出成功');
    }

    /**
     *  登录之后更改状态，然后把登录信息存入登录日志表中
     * @param string $userId
     * @return bool
     */
    public function updateLogin($userId = '') {
        $publicInfo = new Functions();
        $addLogInfo['user_id'] = $userId;
        $addLogInfo['login_name'] = $this->_admin->login_name;
        $addLogInfo['login_time'] = date("Y-m-d H:i:s",time());
        $addLogInfo['login_ip'] = Functions::getRemoteIp();
        $addLogInfo['login_explorer'] = $_SERVER['HTTP_USER_AGENT'];
        $positionInfo = $publicInfo->getIpAddressByBaidu(Yii::$app->getRequest()->getUserIP());
        $addLogInfo['login_position'] = $positionInfo;

        $db = Yii::$app->db;
        $trans = $db->beginTransaction();

        try{
            //再添加登录日志
            $res = AdminLoginLog::insertData($addLogInfo);
            if($res == false) {
                throw new Exception('登录失败');
            }

            //更新最后登录时间
            $update['pre_login_time'] = date('Y-m-d H:i:s');//最后登录时间;
            static::updateData($update,['id' => $userId]);
            $trans->commit();
            return true;
        } catch(Exception $e) {
            $trans->rollBack();
            return false;
        }
    }

    /**
     * @return \cms\modules\common\models\Admin|null
     */
    protected function getAdmin() {
        if ($this->_admin === null) {
            $this->_admin = \cms\modules\common\models\Admin::findByUsername($this->login_name);
        }

        return $this->_admin;
    }

    public function onGenerateAccessToken() {
        if (!static::authKeyIsValid($this->_admin->access_token)) {
            $this->_admin->generateAuthKey();
            $this->_admin->save(false);
            Yii::$app->user->login($this->_admin,Yii::$app->params['user.AccessToken']);
        }
    }
    //============================= 登录结束 =============================

    //============================= 管理员操作 =============================

    /**
     * 返回列表数据
     * @param int $page
     * @param int $size
     * @param array $search
     * @return array
     */
    public function getListData($page = 1, $size = 20, $search = []) {
        try {

            //搜索条件
            $searchWhere  = $this->getSearch($search);//自定义搜索条件

            $query = new \common\models\admin\Admin();

            $count = 0;
            //得到文章的总数
            if(isset($searchWhere['andWhere'])){
                $count = $query::getObjectCountByAndWhere($searchWhere['where'], $searchWhere['andWhere'])->count();
            }
            $data = static::setPageinationAPI($page, $size, $count);

            //设置分页
            $offset = ($data['page'] - 1) * $size;

            //排序 order
            $orderSql = 'id ASC';

            if(isset($searchWhere['andWhere'])){
                $query = $query::getObjectByAndWhere($searchWhere['where'],$searchWhere['andWhere'], '*', $orderSql, $offset, $size);
            }

            $data['data'] = $this->handelList($query);

            return Functions::formatRestAPI(0, '', $data);
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    /**
     * 自定义参数的搜索  搜索,搜索也分每一列
     * 这里要根据业务逻辑进行修改
     * @param array $search
     * @return array
     */
    public function getSearch ($search = []) {
        $where = [];
        $andWhere = [];
        $search = json_decode($search,true);
        if(!empty($search)){
            $status = isset($search['status']) ? $search['status'] : '';

            if($status) {
                $where['status'] = (int) $status;
            }
        }
        return [
            'where' => $where,
            'andWhere' => $andWhere
        ];
    }

    /**
     * 处理初始化数据
     * @param $query
     * @return mixed
     */
    public function handelList($query) {
        if (empty($query)) {
            return null;
        }
        $list = $query->with(['role'])
            ->asArray()->all();

        foreach($list as $key => $value) {

            $list[$key]['id'] = (int) ($value['id']);
            $list[$key]['login_name'] = $value['login_name'];
            $list[$key]['role_name'] = $value['role'] ? $value['role']['role_name'] : '';

        }
        return $list;
    }

    /**
     * 获取特定管理员信息
     * @param int $userId
     * @return array|null|\yii\db\ActiveRecord
     */
    public function getCurrentAdminInfo($userId = 0) {
        $id = $userId ? $userId : Yii::$app->user->getId();
        $where['id'] = $id;
        $adminInfo = static::getOneByWhere($where,'login_name,pre_login_time,role_type,id');
        if ($adminInfo) {
            $adminRoleInfo = AdminRole::getFormArray(['status' => Status::COMMON_STATUS_SHOW],'id','role_name');
            $adminInfo['role_name'] = '暂无角色';
            if(isset($adminInfo['role_type'])) {
                $adminInfo['role_name'] = $adminRoleInfo[$adminInfo['role_type']];
            }
            return $adminInfo;
        }
    }

    /**
     * 添加管理员
     * @return array
     */
    public function saveInfo() {
        try {
            $post = Yii::$app->request->post();
            $user = static::checkLogin();


            if (empty($post['login_name'])) {
                throw new Exception('登录名不能为空');
            }
            if (empty($post['nick_name'])) {
                throw new Exception('昵称不能为空');
            }
            if (empty($post['role_type'])) {
                throw new Exception('角色不能为空');
            }
            $data['nick_name'] = trim($post['nick_name']);
            $data['login_name'] = trim($post['login_name']);

            if (strlen($data['login_name']) > 12) {
                throw new Exception('用户太长，最多12位');
            }

            $data['role_type'] = (int) $post['role_type'];

            if (strlen($post['password']) > 18) {
                throw new Exception('密码最多18位');
            }

            if (!empty($post['password'])) {
                $data['password_hash'] = Yii::$app->security->generatePasswordHash($post['password']);
            }




            $checkLoginName = static::getOneByWhere(['login_name' => $data['login_name']]);

            if ($post['id']) {
                if ($post['id'] == 1 && $user['id'] != 1) {
                    throw new Exception('神仙账号，凡人速速退下！');
                }
                if ($checkLoginName && $checkLoginName['id'] != $post['id']) {
                    throw new Exception('用户名重复');
                }
                $data['update_time'] = date('Y-m-d H:i:s');
                $res = static::updateDataWithLog($data, ['id' => $post['id']]);
                if ($res === false) {
                    throw new Exception('系统错误，请联系开发小哥哥');
                }
            } else {
                if ($checkLoginName) {
                    throw new Exception('用户名重复');
                }
                $data['create_time'] = date('Y-m-d H:i:s');
                $res = static::insertDataWithLog($data);
                if ($res === false) {
                    throw new Exception('系统错误，请联系开发小哥哥');
                }

            }
            return Functions::formatRestAPI(0, '操作成功');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    /**
     * 获取编辑信息
     * @return array
     */
    public function getEditInfo($id = 0) {
        try {
            $id = (int) $id;

            if (empty($id)) {
                throw new Exception('未知信息');
            }
            $info = static::getOneByWhere(['id' => $id]);
            if(empty($info)) {
                throw new Exception('用户不存在');
            }

            $result = [
                'login_name' => $info['login_name'],
                'nick_name' => $info['nick_name'],
                'role_type' => $info['role_type'],
            ];

            return Functions::formatRestAPI(0, '', $result);
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }

    }

    /**
     * 修改角色
     * @return array
     */
    public function editRole() {
        $data = Yii::$app->request->post();
        $where['id'] = intval($data['id']);
        $updateInfo['role_type'] = intval($data['role_type']);
        $updateInfo['update_time'] = date('Y-m-d H:i:s');
        $flag = static::updateDataWithLog($updateInfo, $where);
        if($flag !== false)
        {
            return Functions::formatJson(1000,'分配成功');
        }
        return Functions::formatJson(1001,'分配失败');
    }

    public function switchStatusAdmin() {
        try {

            $post = \Yii::$app->request->post();

            $id = $post['id'];
            if (empty($id)) {
                throw new Exception('未知信息');
            }

            if ($id == 1) {
                throw new Exception('此乃神仙账号，岂能容尔等凡人操作！');
            }

            $data['status'] = (int) $post['status'];
            $data['update_time'] = date("Y-m-d H:i:s");
            $res = static::updateData($data, ['id' => $id]);
            if ($res === false) {
                throw new Exception('系统错误，请联系开发小哥哥');
            }
            return Functions::formatRestAPI(0, '切换成功');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    public function getBaseInfo() {
        try {
            $adminInfo = (new Admin())->checkLogin();

            $result = [
                'name' => $adminInfo['nick_name'],
                'user_id' => $adminInfo['id'],
                'access' => ['super_admin'],
                'avator' => 'https://file.iviewui.com/dist/a0e88e83800f138b94d2414621bd9704.png'
            ];

            return Functions::formatRestAPI(0, '', $result);
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    public function getMfa() {
        try {
            $post = Yii::$app->request->get();

            if (empty($post['id'])) {
                throw new Exception('参数错误');
            }

            $admin = static::getOneInfoById($post['id']);

            $mfa = new GoogleAuthenticator();

            $sec = $mfa->createSecret();

            $url = $mfa->getQRCodeGoogleUrl("掌上益拍（" . $admin['login_name'] . "）", $sec);

            $data = [
                "url" => $url,
                "sec" => $sec
            ];

            return Functions::formatRestAPI(0,'', $data);
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    public function bindMfa() {
        try {
            $admin = (new Admin())->checkLogin();

            if ($admin['id'] != 1) {
                throw new Exception('只有超级管理员才可以操作');
            }

            $post = Yii::$app->request->post();

            $id = $post['id'];
            if (empty($id)) {
                throw new Exception('参数错误');
            }
            $sec = $post['sec'];
            if (empty($sec)) {
                throw new Exception('秘钥获取失败');
            }

            $code = $post['code'];
            if (empty($code)) {
                throw new Exception('请输入动态口令');
            }

            //对用户输入的6位动态码进行校验，参数$sec是与此用户关联的秘钥
            $obj = new GoogleAuthenticator();
            $ret = $obj->verifyCode($sec, $code);

            if (!$ret) {
                throw new Exception('校验失败，请重新绑定');
            }

            $up['is_mfa'] = Status::COMMON_RADIO_YES;
            $up['mfa_sec'] = $sec;

            static::updateData($up, ['id' => $id]);

            return Functions::formatRestAPI(0,'绑定成功');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }

    public function unbindMfa() {
        try {
            $admin = (new Admin())->checkLogin();
            $post = Yii::$app->request->get();

            $id = $post['id'];
            if (empty($id)) {
                throw new Exception('参数错误');
            }

            if ($admin['id'] != 1) {
                throw new Exception('只有超级管理员才可以操作');
            }

//            if ($admin['id'] != 1) {
//                $adminInfo = static::getOneInfoById($id);
//                if ($adminInfo['is_mfa'] == Status::COMMON_RADIO_NO) {
//                    throw new Exception('该账号未绑定MFA设备');
//                }
//
//                $sec = $adminInfo['mfa_sec'];
//                $code = $post['code'];
//                if (empty($code)) {
//                    throw new Exception('请输入动态口令');
//                }
//
//                //对用户输入的6位动态码进行校验，参数$sec是与此用户关联的秘钥
//                $obj = new GoogleAuthenticator();
//                $ret = $obj->verifyCode($sec, $code);
//
//                if (!$ret) {
//                    throw new Exception('校验失败，请重新绑定');
//                }
//            }

            $up['is_mfa'] = Status::COMMON_RADIO_NO;
            $up['mfa_sec'] = '';

            static::updateData($up, ['id' => $id]);

            return Functions::formatRestAPI(0,'绑定成功');
        } catch (Exception $e) {
            return Functions::formatRestAPI(1, $e->getMessage());
        }
    }
}
